<?php

date_default_timezone_set("Asia/Bangkok");

require 'system.inc.php';

/* ==========================  Class   ============================ */

class RequestResponse {

    private $code = 200;
    private $body = "";
    private $content_type = "text/html";
    private $charset = "UTF-8";

    public function __construct($code = 200, $body = '', $content_type = 'application/json', $charset = "UTF-8") {
        $this->code = $code;
        $this->body = $body;
        $this->content_type = $content_type;
        $this->charset = $charset;
    }

    public function checkIfNonceMath($if_nonce_match) {
        //if ($if_nonce_match == null)
        $this->process();

//        if (md5(base64_encode($this->body)) == $if_nonce_match) {
//            http_response_code(304);
//        } else {
//            $this->process();
//        }
    }

    public function setBodyJSON($datas) {
        $response_body = array(
            "data" => $datas,
        );
        $this->body = json_encode($response_body);
    }

    public function process() {
        http_response_code($this->code);
        header("Content-type: $this->content_type; charset=$this->charset");
        if ($this->code == 200)
            header("Etag: " . md5(base64_encode($this->body)));
        die($this->body);
    }

}

/* ==========================  Class   ============================ */

class Application {

    var $name;
    var $action;
    var $path;

    public function __construct($apiRootPath) {
        if (!isset($_GET["r"])) {
            $response = new RequestResponse(404, "<B>Không tồn tại đường dẫn này</B>");
            $response->process();
        } else {
            $r_str = explode("/", $_GET["r"]);
            $this->name = $r_str[0];
            $this->action = count($r_str) >= 2 ? $r_str[1] : "default";
            $this->path = $apiRootPath . '/' . $this->name . '.api.php';
        }
    }

    public function run() {
        try {
            if (file_exists($this->path)) {
                require $this->path;
            } else {
                $response = new RequestResponse(500, "<B>Không tồn tại lớp $this->name này</B>");
                $response->process();
            }

            if (!class_exists($this->name)) {
                $response = new RequestResponse(500, "<B>Không tồn tại lớp $this->name này</B>");
                $response->process();
            } else {
                $router = new $this->name;
                if (method_exists($router, 'action' . $this->action)) {
                    call_user_func(array($router, 'action' . $this->action));
                } else {
                    $response = new RequestResponse(500, "<B>Không tồn tại action $this->action này</B>");
                    $response->process();
                }
            }
        } catch (exception $e) {
            $response = new RequestResponse(500, "<B>Internal Sever Error : $e</B>");
            $response->process();
        }
    }

}

/* ==========================  Class   ============================ */

class RequestParams {

    private $params = Array();

    public function __construct($request_method) {
        $this->_parseParams($request_method);
    }

    public function get($name, $default = null) {
        if (isset($this->params[$name])) {
            return $this->params[$name];
        } else {
            return $default;
        }
    }

    private function _parseParams($request_method) {
        if ($request_method == "PUT" || $request_method == "DELETE") {
            parse_str(file_get_contents('php://input'), $this->params);
            $GLOBALS["_{$method}"] = $this->params;
            $_REQUEST = $this->params + $_REQUEST;
        } else if ($request_method == "GET") {
            $this->params = $_GET;
        } else if ($request_method == "POST") {
            $this->params = $_POST;
        }
    }

}

/* ==========================  Class   ============================ */

class RequestHeader {

    private $header = Array();

    public function __construct() {
        $this->header = getallheaders();
    }

    public function get($name, $default = null) {
        if (isset($this->header[$name])) {
            return $this->header[$name];
        } else {
            return $default;
        }
    }

}

class DataVaidate {

    public static function request_method_validate($accept_method) {
        return $accept_method == get_request_method();
    }

    public static function variable_validate($var_value, $var_type = "integer") {
        switch ($var_type) {
            case "integer":
                return preg_match("'^[0-9]+$'", $var_value);
            case "string":
                return is_string($var_value);
            case "boolean":
                return filter_var($var_value, FILTER_VALIDATE_BOOLEAN);
            case "ip":
                return filter_var($var_value, FILTER_VALIDATE_IP);
            case "float":
                return filter_var($var_value, FILTER_VALIDATE_FLOAT);
            case "email":
                return filter_var($var_value, FILTER_VALIDATE_EMAIL);
            case "url":
                return filter_var($var_value, FILTER_VALIDATE_URL);
            case "serialize":
                return @unserialize($var_value) !== false || $var_value === 'b:0;' ? true : false;
            default:
                $response = new RequestResponse(500, "Can not evaluator $var with type : $var_type");
                $response->process();
        }
    }

}

/* ==========================  Class   ============================ */

abstract class WebService {

    protected $request_method;
    protected $request_header;
    private $request_params = null;

    public function __construct() {
        $this->request_method = get_request_method();
        $this->request_header = new RequestHeader();
        if (isset($_GET['dev'])) {
            save_logs('request.log', "Request Method: " . get_request_method() . " \n" . var_export($_REQUEST, 1));
        }
    }

    protected function getRequestParams() {
        if ($this->request_params == null)
            $this->request_params = new RequestParams($this->request_method);
        return $this->request_params;
    }

    public function actionDefault() {
        $response = new RequestResponse(400, "Default action not accept in this API!!!");
        $response->process();
    }

}

?>